<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * 能力评定模型
 * 记录员工能力评定的详细结果
 */
class AbilityAssessment extends Model
{
    use HasFactory;

    /**
     * 表名
     */
    protected $table = 'ability_assessments';

    /**
     * 可填充字段
     */
    protected $fillable = [
        'employee_id',
        'evaluator_id',
        'position_id',
        'position_name',
        'assessment_type',
        'assessment_period',
        'assessment_date',
        'effective_date',
        'dimension_scores',
        'total_score',
        'weighted_score',
        'overall_rating',
        'strengths',
        'weaknesses',
        'improvement_plan',
        'development_suggestions',
        'comments',
        'goals',
        'achievements',
        'kpis',
        'competency_analysis',
        'skill_gaps',
        'training_needs',
        'current_salary',
        'recommended_salary',
        'salary_adjustment_reason',
        'salary_effective_date',
        'promotion_recommended',
        'recommended_position',
        'promotion_reason',
        'promotion_effective_date',
        'status',
        'submitted_by',
        'submitted_at',
        'reviewed_by',
        'reviewed_at',
        'approved_by',
        'approved_at',
        'review_comments',
        'attachments',
        'version',
        'is_latest',
        'is_active',
    ];

    /**
     * 字段类型转换
     */
    protected $casts = [
        'assessment_date' => 'date',
        'effective_date' => 'date',
        'submitted_at' => 'date',
        'reviewed_at' => 'date',
        'approved_at' => 'date',
        'salary_effective_date' => 'date',
        'promotion_effective_date' => 'date',
        'is_latest' => 'boolean',
        'is_active' => 'boolean',
        'promotion_recommended' => 'boolean',
        'total_score' => 'decimal:2',
        'weighted_score' => 'decimal:2',
        'current_salary' => 'decimal:2',
        'recommended_salary' => 'decimal:2',
        'dimension_scores' => 'array',
        'goals' => 'array',
        'achievements' => 'array',
        'kpis' => 'array',
        'competency_analysis' => 'array',
        'skill_gaps' => 'array',
        'training_needs' => 'array',
        'attachments' => 'array',
        'version' => 'integer',
    ];

    /**
     * 日期字段
     */
    protected $dates = [
        'assessment_date',
        'effective_date',
        'submitted_at',
        'reviewed_at',
        'approved_at',
        'salary_effective_date',
        'promotion_effective_date',
        'created_at',
        'updated_at',
    ];

    // ============ 常量定义 ============

    public const TYPE_ANNUAL = 'annual';
    public const TYPE_PROBATION = 'probation';
    public const TYPE_PROMOTION = 'promotion';
    public const TYPE_REGULAR = 'regular';

    public const STATUS_DRAFT = 'draft';
    public const STATUS_SUBMITTED = 'submitted';
    public const STATUS_REVIEWED = 'reviewed';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';

    public const RATING_A = 'A';
    public const RATING_B = 'B';
    public const RATING_C = 'C';
    public const RATING_D = 'D';
    public const RATING_F = 'F';

    // ============ 关联关系 ============

    /**
     * 关联被评定员工
     */
    public function employee(): BelongsTo
    {
        return $this->belongsTo(Employee::class);
    }

    /**
     * 关联评定人
     */
    public function evaluator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'evaluator_id');
    }

    // ============ 访问器 ============

    /**
     * 获取评定类型标签
     */
    public function getAssessmentTypeLabelAttribute(): string
    {
        return match($this->assessment_type) {
            self::TYPE_ANNUAL => '年度考核',
            self::TYPE_PROBATION => '试用期考核',
            self::TYPE_PROMOTION => '晋升考核',
            self::TYPE_REGULAR => '定期考核',
            default => $this->assessment_type ?? '未知'
        };
    }

    /**
     * 获取状态标签
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            self::STATUS_DRAFT => '草稿',
            self::STATUS_SUBMITTED => '已提交',
            self::STATUS_REVIEWED => '已审核',
            self::STATUS_APPROVED => '已批准',
            self::STATUS_REJECTED => '已驳回',
            default => $this->status ?? '未知'
        };
    }

    /**
     * 获取总体评级标签
     */
    public function getOverallRatingLabelAttribute(): string
    {
        return match($this->overall_rating) {
            self::RATING_A => '优秀',
            self::RATING_B => '良好',
            self::RATING_C => '合格',
            self::RATING_D => '基本合格',
            self::RATING_F => '不合格',
            default => $this->overall_rating ?? '未知'
        };
    }

    /**
     * 获取薪资调整建议
     */
    public function getSalaryAdjustmentSuggestionAttribute(): string
    {
        if (!$this->current_salary || !$this->recommended_salary) {
            return '无建议';
        }

        $difference = $this->recommended_salary - $this->current_salary;
        $percentage = round(($difference / $this->current_salary) * 100, 1);

        if ($difference > 0) {
            return "建议上调 {$percentage}% (+{$difference})";
        } elseif ($difference < 0) {
            return "建议下调 {$percentage}% ({$difference})";
        } else {
            return '维持不变';
        }
    }

    /**
     * 获取是否建议晋升标签
     */
    public function getPromotionRecommendedLabelAttribute(): string
    {
        return $this->promotion_recommended ? '建议晋升' : '不建议晋升';
    }

    /**
     * 获取考核周期格式化
     */
    public function getAssessmentPeriodFormattedAttribute(): string
    {
        if (!$this->assessment_period) {
            return '未知周期';
        }

        // 处理常见的周期格式
        if (preg_match('/^(\d{4})-Q(\d)$/', $this->assessment_period, $matches)) {
            return "{$matches[1]}年第{$matches[2]}季度";
        }

        if (preg_match('/^(\d{4})-H(\d)$/', $this->assessment_period, $matches)) {
            return "{$matches[1]}年第{$matches[2]}半年度";
        }

        return $this->assessment_period;
    }

    /**
     * 获取评分详情
     */
    public function getDimensionScoresDetailAttribute(): array
    {
        if (!$this->dimension_scores) {
            return [];
        }

        $details = [];
        foreach ($this->dimension_scores as $score) {
            $dimension = AbilityDimension::find($score['dimension_id'] ?? null);
            $details[] = [
                'dimension_name' => $dimension?->name ?? '未知维度',
                'score' => $score['score'] ?? null,
                'comment' => $score['comment'] ?? null,
            ];
        }

        return $details;
    }

    // ============ 作用域 ============

    /**
     * 最新版本作用域
     */
    public function scopeLatest($query)
    {
        return $query->where('is_latest', true);
    }

    /**
     * 按评定类型筛选作用域
     */
    public function scopeByType($query, $type)
    {
        return $query->where('assessment_type', $type);
    }

    /**
     * 按评定周期筛选作用域
     */
    public function scopeByPeriod($query, $period)
    {
        return $query->where('assessment_period', $period);
    }

    /**
     * 按状态筛选作用域
     */
    public function scopeByStatus($query, $status)
    {
        return $query->where('status', $status);
    }

    /**
     * 按评级筛选作用域
     */
    public function scopeByRating($query, $rating)
    {
        return $query->where('overall_rating', $rating);
    }

    /**
     * 年度考核作用域
     */
    public function scopeAnnual($query)
    {
        return $query->where('assessment_type', self::TYPE_ANNUAL);
    }

    /**
     * 已批准作用域
     */
    public function scopeApproved($query)
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    /**
     * 建议晋升作用域
     */
    public function scopePromotionRecommended($query)
    {
        return $query->where('promotion_recommended', true);
    }

    // ============ 业务方法 ============

    /**
     * 提交评定
     */
    public function submit(string $submittedBy): bool
    {
        $this->status = self::STATUS_SUBMITTED;
        $this->submitted_by = $submittedBy;
        $this->submitted_at = now();

        return $this->save();
    }

    /**
     * 审核评定
     */
    public function review(string $reviewedBy, ?string $comments = null): bool
    {
        $this->status = self::STATUS_REVIEWED;
        $this->reviewed_by = $reviewedBy;
        $this->reviewed_at = now();
        $this->review_comments = $comments;

        return $this->save();
    }

    /**
     * 批准评定
     */
    public function approve(string $approvedBy): bool
    {
        $this->status = self::STATUS_APPROVED;
        $this->approved_by = $approvedBy;
        $this->approved_at = now();

        return $this->save();
    }

    /**
     * 驳回评定
     */
    public function reject(string $approvedBy, ?string $comments = null): bool
    {
        $this->status = self::STATUS_REJECTED;
        $this->approved_by = $approvedBy;
        $this->approved_at = now();
        $this->review_comments = $comments;

        return $this->save();
    }

    /**
     * 计算总分和加权分
     */
    public function calculateScores(): bool
    {
        if (!$this->dimension_scores) {
            return false;
        }

        $totalScore = 0;
        $totalWeight = 0;
        $weightedScore = 0;

        foreach ($this->dimension_scores as $scoreData) {
            $dimensionId = $scoreData['dimension_id'] ?? null;
            $score = $scoreData['score'] ?? 0;

            if ($dimensionId) {
                $dimension = AbilityDimension::find($dimensionId);
                if ($dimension && $dimension->is_active) {
                    $weight = $dimension->weight;
                    $totalScore += $score;
                    $totalWeight += $weight;
                    $weightedScore += ($score * $weight / 100);
                }
            }
        }

        $this->total_score = $totalScore;
        $this->weighted_score = $totalWeight > 0 ? round($weightedScore, 2) : 0;

        return $this->save();
    }

    /**
     * 生成总体评级
     */
    public function generateOverallRating(): bool
    {
        if (!$this->weighted_score) {
            return false;
        }

        $score = $this->weighted_score;

        if ($score >= 90) {
            $this->overall_rating = self::RATING_A;
        } elseif ($score >= 80) {
            $this->overall_rating = self::RATING_B;
        } elseif ($score >= 70) {
            $this->overall_rating = self::RATING_C;
        } elseif ($score >= 60) {
            $this->overall_rating = self::RATING_D;
        } else {
            $this->overall_rating = self::RATING_F;
        }

        return $this->save();
    }

    /**
     * 创建新版本
     */
    public function createNewVersion(): self
    {
        // 将当前版本设为非最新
        $this->is_latest = false;
        $this->save();

        // 创建新版本
        $newAssessment = $this->replicate();
        $newAssessment->version = $this->version + 1;
        $newAssessment->is_latest = true;
        $newAssessment->status = self::STATUS_DRAFT;
        $newAssessment->save();

        return $newAssessment;
    }

    /**
     * 更新维度评分
     */
    public function updateDimensionScore(int $dimensionId, float $score, ?string $comment = null): bool
    {
        $scores = $this->dimension_scores ?? [];

        $found = false;
        foreach ($scores as &$scoreData) {
            if (($scoreData['dimension_id'] ?? null) === $dimensionId) {
                $scoreData['score'] = $score;
                $scoreData['comment'] = $comment;
                $found = true;
                break;
            }
        }

        if (!$found) {
            $scores[] = [
                'dimension_id' => $dimensionId,
                'score' => $score,
                'comment' => $comment,
            ];
        }

        $this->dimension_scores = $scores;

        // 重新计算总分
        $this->calculateScores();
        $this->generateOverallRating();

        return $this->save();
    }

    // ============ 静态方法 ============

    /**
     * 获取评定类型选项
     */
    public static function getAssessmentTypeOptions(): array
    {
        return [
            self::TYPE_ANNUAL => '年度考核',
            self::TYPE_PROBATION => '试用期考核',
            self::TYPE_PROMOTION => '晋升考核',
            self::TYPE_REGULAR => '定期考核',
        ];
    }

    /**
     * 获取评定状态选项
     */
    public static function getStatusOptions(): array
    {
        return [
            self::STATUS_DRAFT => '草稿',
            self::STATUS_SUBMITTED => '已提交',
            self::STATUS_REVIEWED => '已审核',
            self::STATUS_APPROVED => '已批准',
            self::STATUS_REJECTED => '已驳回',
        ];
    }

    /**
     * 获取评级选项
     */
    public static function getRatingOptions(): array
    {
        return [
            self::RATING_A => '优秀',
            self::RATING_B => '良好',
            self::RATING_C => '合格',
            self::RATING_D => '基本合格',
            self::RATING_F => '不合格',
        ];
    }

    /**
     * 创建评定模板
     */
    public static function createTemplate(
        int $employeeId,
        int $evaluatorId,
        string $assessmentType,
        string $assessmentPeriod
    ): self {
        $activeDimensions = AbilityDimension::active()->orderBySort()->get();

        $dimensionScores = [];
        foreach ($activeDimensions as $dimension) {
            $dimensionScores[] = [
                'dimension_id' => $dimension->id,
                'score' => null,
                'comment' => null,
            ];
        }

        return self::create([
            'employee_id' => $employeeId,
            'evaluator_id' => $evaluatorId,
            'assessment_type' => $assessmentType,
            'assessment_period' => $assessmentPeriod,
            'assessment_date' => now(),
            'dimension_scores' => $dimensionScores,
            'status' => self::STATUS_DRAFT,
            'version' => 1,
            'is_latest' => true,
            'is_active' => true,
        ]);
    }

    /**
     * 获取员工最新评定
     */
    public static function getLatestAssessment(int $employeeId, ?string $assessmentType = null): ?self
    {
        $query = self::where('employee_id', $employeeId)
                    ->where('is_latest', true)
                    ->where('is_active', true);

        if ($assessmentType) {
            $query->where('assessment_type', $assessmentType);
        }

        return $query->latest('assessment_date')->first();
    }

    /**
     * 验证评定数据
     */
    public static function validateAssessmentData(array $data): array
    {
        $errors = [];

        // 必填字段验证
        $requiredFields = ['employee_id', 'evaluator_id', 'assessment_type', 'assessment_date'];
        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                $errors[] = "{$field} 字段不能为空";
            }
        }

        // 评定类型验证
        $validTypes = array_keys(self::getAssessmentTypeOptions());
        if (!empty($data['assessment_type']) && !in_array($data['assessment_type'], $validTypes)) {
            $errors[] = "无效的评定类型";
        }

        // 状态验证
        $validStatuses = array_keys(self::getStatusOptions());
        if (!empty($data['status']) && !in_array($data['status'], $validStatuses)) {
            $errors[] = "无效的状态";
        }

        // 评级验证
        $validRatings = array_keys(self::getRatingOptions());
        if (!empty($data['overall_rating']) && !in_array($data['overall_rating'], $validRatings)) {
            $errors[] = "无效的评级";
        }

        // 分数验证
        if (!empty($data['total_score']) && (!is_numeric($data['total_score']) || $data['total_score'] < 0)) {
            $errors[] = "总分必须是有效的非负数";
        }

        if (!empty($data['weighted_score']) && (!is_numeric($data['weighted_score']) || $data['weighted_score'] < 0)) {
            $errors[] = "加权分必须是有效的非负数";
        }

        // 薪资验证
        if (!empty($data['current_salary']) && (!is_numeric($data['current_salary']) || $data['current_salary'] <= 0)) {
            $errors[] = "当前薪资必须是有效的正数";
        }

        if (!empty($data['recommended_salary']) && (!is_numeric($data['recommended_salary']) || $data['recommended_salary'] <= 0)) {
            $errors[] = "建议薪资必须是有效的正数";
        }

        return $errors;
    }
}
